#ifndef USUARIO_H_
#define USUARIO_H_

#include "Interesse.h"
#include "Livro.h"
#include "../estruturas/Lista.h"

#include <string>
#include <vector>

using namespace std;

/**
 * @class Usuario Usuario.h "src/kisebo/Usuario.h"
 * @brief Classe para controle de usuario.
 * A classe Usuario é um detalhamento das pessoas que podem
 * acessar o sistema. Dividindo o usuário em dois tipos: \n
 * - Cliente:
 * 	-# Cadastrar interesse
 * 	-# Cadastrar Cliente
 * 	-# Venda
 * - Funcionario:
 * 	-# Cadastrar Livro
 * 	-# Cadastrar Cliente
 * 	-# Venda
*/
class Usuario
{

public:

	/**
	 *  @enum <ENUM_TIPO>
	 * 	@brief Enumerator com o tipo do usuário logado.
	 * 	Enumerator para controlar o tipo do usuário,
	 * 	para saber exatamente qual os acessos permitidos.
	*/
	enum ENUM_TIPO {
		/**
		 * Usuário Cliente Value 1
		 */
		CLIENTE = 1,

		/**
		 * Usuário Funcionario Value 2
		 */
		FUNCIONARIO = 2
	};

private:

	/**
	 * Código de identificação
	 */
	long id;

	/**
	 * Login do Usuário
	 */
	string login;

	/**
	 * Tipo do usuário
	 */
	ENUM_TIPO tipoUsuario;

	/**
	 * Senha para acesso
	 */
	string senha;

	/**
	 * Nome do usuário
	 */
	string nome;

	/**
	 * Cep do endereço
	 */
	string cep;

	/**
	 * Endereço detalhado
	 */
	string endereco;

	/**
	 * Complemento do endereço
	 */
	string complemento;

	/**
	 * Telefone do usuário
	 */
	string telefone;

	/**
	 * Interesses (selecionados)
	 */
	vector<Interesse> interesses;

	/**
	 * Livros de interesse (selecionados)
	 */
	vector<Livro> livrosDeInteresse;

public:

	/**
	 * @fn Usuario()
	 * @brief Cria uma instancia padrão
	 * Esse método cria uma instancia do Usuario, \n
	 * lembrando que informa o id do usuário como -1 por padrão.
	 */
	Usuario();

	/**
	  * @fn Usuario(const Usuario &_copia)
	  * @brief Construtor por cópia.
	  * Utilizado para criar uma instancia do objeto quando queremos
	  * criar uma cópia do objeto já existente.
	  * @param _copia um usuário preenchido.
	 */
	Usuario(const Usuario &_copia);

	/**
	  * @fn virtual ~Usuario()
	  * @brief Destrutor da entidade
	  * Utilizado para liberar espaço na mémoria, eliminando a instancia
	  * do objeto criado.
	 */
	virtual ~Usuario();

    /**
     *  @fn void AdicionaInteresse(Interesse _interesse)
     *  @brief Inserir um interesse na lista de interesses
     *  @param _interesse novo interesse.
     *  @see Interesse
    */
	void AdicionaInteresse(Interesse _interesse);

    /**
     *  @fn Interesse GetInteresse(int _posicao)
     *  @brief Um interesse selecionado na lista de interesses.
     *  @return Interesse da lista de interesses do usuário..
     *  @see Interese
    */
	Interesse GetInteresse(int _posicao);

	/**
     *  @fn void AdicionaLivroDeInteresse(Livro _livro)
     *  @brief Inserir um livro na lista de livros.
     *  @param _livro novo livro.
	 */
	void AdicionaLivroDeInteresse(Livro _livro);

    /**
     *  @fn Livro GetLivroDeInteresse(int _posicao)
     *  @brief Retorna um liro da lista de livros do usuário.
     *  @return retorna um livro.
    */
	Livro GetLivroDeInteresse(int _posicao);

    /**
     *  @fn long GetID()
     *  @brief Retorna o código de identificação do usuário.
     *  @return código de identificação.
    */
	long GetID();

    /**
     *  @fn void SetID( long _id)
     *  @brief Inserir o código de identificação.
     *  @param _id código de identificação.
    */
	void SetID( long _id);

    /**
     *  @fn string GetLogin()
     *  @brief Retorna o login de acesso utilizado pelo usuário.
     *  @return login de acesso.
    */
	string GetLogin();

    /**
     *  @fn void SetLogin( string _login)
     *  @brief Inserir o login de acesso.
     *  @param _login login de acesso.
    */
	void SetLogin( string _login);

    /**
     *  @fn void SetSenha( string _senha)
     *  @brief Inserir a senha do usuário.
     *  @param _senha senha.
    */
	void SetSenha( string _senha);

    /**
     *  @fn ENUM_TIPO GetTipoUsuario()
     *  @brief Retorna o tipo de usuário.
     *  @return tipo de usuário.
     *  @see Usuario::ENUM_TIPO
    */
    ENUM_TIPO GetTipoUsuario();

    /**
     *  @fn void SetTipoUsuario(ENUM_TIPO _tipoUsuario)
     *  @brief Inserir o tipo do usuário.
     *  @param _tipoUsuario tipo do usuário.
     *  @see Usuario::ENUM_TIPO
    */
    void SetTipoUsuario(ENUM_TIPO _tipoUsuario);

    /**
     *  @fn string GetNome()
     *  @brief Retorna o nome do usuário.
     *  @return nome.
    */
    string GetNome();

    /**
     *  @fn void SetNome(string _nome)
     *  @brief Inserir o nome do usuário.
     *  @param _nome nome do usuáiro.
    */
    void SetNome(string _nome);

    /**
     *  @fn string GetCep()
     *  @brief Retorna o cep do endereço.
     *  @return cep do endereço.
    */
    string GetCep();

    /**
     *  @fn void SetCep(string _cep)
     *  @brief Inserir o cep do endereço do usuário.
     *  @param _cep cep do endereço.
    */
    void SetCep(string _cep);

    /**
     *  @fn string GetEndereco()
     *  @brief Retorna o endereço do usuario.
     *  @return endereço do usuário.
    */
    string GetEndereco();

    /**
     *  @fn void SetEndereco(string _endereco)
     *  @brief Inserir o endereço do usuário.
     *  @param _endereco endereço do usuário.
    */
    void SetEndereco(string _endereco);

    /**
     *  @fn string GetComplemento()
     *  @brief Retorna o complemento do endereço do usuário.
     *  @return complemento do endereço.
    */
    string GetComplemento();

    /**
     *  @fn void SetComplemento(string _complemento)
     *  @brief Inserir o complemento do endereço do usuário.
     *  @param _complemento complemento do endereço
    */
    void SetComplemento(string _complemento);

    /**
     *  @fn string GetTelefone()
     *  @brief Retorna o telefone do usuário.
     *  @return telefone do usuário.
    */
    string GetTelefone();

    /**
     *  @fn void SetTelefone(string _telefone)
     *  @brief Inserir o telefone do usuário
     *  @param _telefone telefone do usuário.
    */
    void SetTelefone(string _telefone);

    /**
     *  @fn friend ostream& operator<<(ostream &_out, const Usuario &_usuario)
     *  @brief Sobrescreve a impressão da entidade Usuario
     *  @param _out saida do objeto.
     *  @param _usuario O usuario desejado.
     *  @return out Impressão formatada.
    */
    friend ostream& operator<<(ostream &_out, const Usuario &_usuario);

    /**
     *  @fn friend ostream& operator<<(ostream &_out, const ENUM_TIPO &_tipo)
     *  @brief Sobrescreve a impressão do ENUM_TIPO
     *  @param _out saida do objeto.
     *  @param _tipo O enumerator desejado.
     *  @return out Impressão formatada.
    */
    friend ostream& operator<<(ostream &_out, const ENUM_TIPO &_tipo);

};

#endif /*USUARIO_H_*/
